﻿using OpenHardwareMonitor.Hardware;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Management;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace InfoMonitor
{
    public partial class Form1 : Form
    {
        UdpClient udpClient;
        Computer computer;
        vis updateVisitor = new vis();
        Dictionary<string, string> sensorValue = new Dictionary<string, string>();
        bool Exit = false;
        List<IPEndPoint> ips = new List<IPEndPoint>();
        //if (!File.Exists(cfgpath))
        string cfgpath = System.IO.Path.GetTempPath() + System.Reflection.Assembly.GetExecutingAssembly().GetName().Name + ".cfg";
        Dictionary<string, int> cfg = new Dictionary<string, int>();
        void loadcfg()
        {
            if (!File.Exists(cfgpath)) savecfg();
            var sr = new StreamReader(new FileStream(cfgpath, FileMode.OpenOrCreate));
            while (!sr.EndOfStream)
            {
                var line = sr.ReadLine();
                var data = line.Split(':');
                try
                {
                    cfg[data[0]] = int.Parse(data[1]);
                }
                catch { }
            }
            sr.Close();
        }
        void savecfg()
        {
            cfg["置顶"] = TopMost?1:0;
            cfg["自动发送"] = cb_sendallEnable.Checked?1:0;
            try
            {
                cfg["端口"] = int.Parse(port_text.Text);
            }
            catch { }
            cfg["透明度"] = trackBar1.Value;
            var sw =new StreamWriter(new FileStream(cfgpath, FileMode.OpenOrCreate));
            foreach(var key in cfg.Keys)
            {
                sw.WriteLine($"{key}:{cfg[key]}");
            }
            sw.Flush();
            sw.Close();
        }
        class vis : IVisitor
        {
            public void VisitComputer(IComputer computer)
            {
                computer.Traverse(this);
            }

            public void VisitHardware(IHardware hardware)
            {
                hardware.Update();
                foreach (IHardware subHardware in hardware.SubHardware)
                    subHardware.Accept(this);
            }

            public void VisitParameter(IParameter parameter){}

            public void VisitSensor(ISensor sensor){}
        }
        protected override CreateParams CreateParams
        {
            get
            {
                const int WS_EX_APPWINDOW = 0x40000;
                const int WS_EX_TOOLWINDOW = 0x80;
                CreateParams cp = base.CreateParams;
                cp.ExStyle &= (~WS_EX_APPWINDOW);
                cp.ExStyle |= WS_EX_TOOLWINDOW;
                return cp;
            }
        }
        protected override void OnClosed(EventArgs e)
        {
            Exit = true;
            退出ToolStripMenuItem_Click(null, null);
            base.OnClosed(e);
        }
        bool init = false;
        
        public Form1()
        {
            InitializeComponent();

            cfg["置顶"] = 0;
            cfg["自动发送"] = 0;
            cfg["端口"] = 511;
            cfg["透明度"] = 100;
            loadcfg();
            if (cfg["置顶"] != 0)
                置顶ToolStripMenuItem_Click(null, null);
            if (cfg["自动发送"] != 0)
                cb_sendallEnable.Checked = true;
            port_text.Text = "" + cfg["端口"];
            trackBar1.Value = cfg["透明度"];
            computer = new Computer();
            computer.Open();
            computer.CPUEnabled = true;
            computer.RAMEnabled = true;
            computer.GPUEnabled = true;
            computer.HDDEnabled = true;
            new System.Threading.Thread(() => {
                while (!Exit)
                {
                    computer.Accept(updateVisitor);
                    int GPUCount = 0;
                    foreach (var hw in computer.Hardware)
                    {
                        if (hw.HardwareType == HardwareType.CPU)
                        {
                            foreach (var sensor in hw.Sensors)
                            {
                                if (sensor.SensorType == SensorType.Temperature)
                                    if (sensor.Name == "CPU Package")
                                        sensorValue["CPU温度"] = sensor.Value.ToString();
                                if (sensor.SensorType == SensorType.Load)
                                    if (sensor.Name == "CPU Total")
                                        sensorValue["CPU使用率"] = sensor.Value.ToString();
                            }
                        }

                        if (hw.HardwareType == HardwareType.GpuAti || hw.HardwareType == HardwareType.GpuNvidia)
                        {
                            foreach (var sensor in hw.Sensors)
                            {
                                if (sensor.SensorType == SensorType.Temperature)
                                    if (sensor.Name == "GPU Core")
                                        sensorValue[$"GPU{(GPUCount > 0 ? "" + GPUCount : "")}温度"] = sensor.Value.ToString();
                                if (sensor.SensorType == SensorType.Load)
                                {
                                    if (sensor.Name == "GPU Core")
                                        sensorValue[$"GPU{(GPUCount > 0 ? "" + GPUCount : "")}使用率"] = sensor.Value.ToString();
                                    if (sensor.Name == "GPU Memory")
                                        sensorValue[$"GPU{(GPUCount > 0 ? "" + GPUCount : "")}内存"] = sensor.Value.ToString();
                                }
                            }
                            sensorValue[$"GPU{(GPUCount > 0 ? "" + GPUCount : "")}名称"] = hw.Name;
                            GPUCount++;
                        }
                        if (hw.HardwareType == HardwareType.RAM)
                        {
                            foreach (var sensor in hw.Sensors)
                            {
                                if (sensor.SensorType == SensorType.Load)
                                    if (sensor.Name == "Memory")
                                        sensorValue["内存使用率"] = sensor.Value.ToString();
                                if (sensor.SensorType == SensorType.Data)
                                    if (sensor.Name == "Used Memory")
                                        sensorValue["使用内存"] = sensor.Value.ToString();
                            }
                        }
                    }
                    System.Threading.Thread.Sleep(1000);
                }
            }).Start();
            Timer t=new Timer();
            t.Interval = 1000;
            t.Tick += (s, e) => {
                
                if (sensorValue.ContainsKey("CPU温度"))
                    cpu_temp.Text = $"{sensorValue["CPU温度"]}℃";
                if (sensorValue.ContainsKey("CPU使用率"))
                    cpu_used.Text = $"{float.Parse(sensorValue["CPU使用率"]):.}%";
                if (sensorValue.ContainsKey("内存使用率"))
                    ram_used.Text = $"{float.Parse(sensorValue["内存使用率"]):.0}%";
                if (sensorValue.ContainsKey("使用内存"))
                    ram_usevalue.Text = $"{float.Parse(sensorValue["使用内存"]):.}/{float.Parse(sensorValue["使用内存"]) / float.Parse(sensorValue["内存使用率"]) * 100:.}G";
                if (sensorValue.ContainsKey("GPU名称"))
                {
                    GPU0_Name.Text = $"{sensorValue["GPU名称"]}".Replace("AMD", "").Replace("NVIDIA", "").Trim();
                    gpu0_temp.Text = $"{sensorValue["GPU温度"]}℃";
                    gpu0_used.Text = $"{sensorValue["GPU使用率"]}%";
                }
                if (sensorValue.ContainsKey("GPU1名称"))
                {
                    panel5.Visible = true ;
                    GPU1_Name.Text = $"{sensorValue["GPU1名称"]}".Replace("AMD", "").Replace("NVIDIA", "").Trim();
                    gpu1_temp.Text = $"{sensorValue["GPU1温度"]}℃";
                    gpu1_used.Text = $"{sensorValue["GPU1使用率"]}%";
                }
                if (cb_sendallEnable.Checked)
                {
                    //sendall($"info");
                    sendall($"info={{\"{cpu_temp.Text}\",\"{cpu_used.Text}\",\"{ram_used.Text}\",\"{ram_usevalue.Text}\",\"{gpu0_temp.Text}\",\"{gpu0_used.Text}\"}}");
                }
            };
            t.Start();
            Width = 48 * 4;
            Height = 48;
            updateips();
            udpClient = new UdpClient();
        }

        float GetCPUTemperature()
        {
            return 0;
        }

        void sendall(string s)
        {
            sendall(Encoding.Default.GetBytes(s));
        }
        void sendall(byte[] data)
        {
            if (udpClient == null)
                return;
            foreach (var ep in ips)
                udpClient.Send(data, data.Length, ep);
        }
        void updateips()
        {
            int port = 0;
            try
            {
                port = int.Parse(port_text.Text);
            }catch
            { return; }
            NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
            ips.Clear();
            foreach (NetworkInterface networkInterface in networkInterfaces)
            {
                if (networkInterface.OperationalStatus == OperationalStatus.Up)
                {
                    IPInterfaceProperties ipProperties = networkInterface.GetIPProperties();

                    foreach (UnicastIPAddressInformation ipAddressInfo in ipProperties.UnicastAddresses)
                    {
                        if (ipAddressInfo.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                        {
                            var target = new IPEndPoint(ipAddressInfo.Address.Address | 0xff000000, port);
                            ips.Add(target);
                        }
                    }
                }
            }
        }
        private void button1_Click(object sender, EventArgs e)
        {
            updateips();
        }
        bool move = false;
        Point StartPoint;
        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            StartPoint = Cursor.Position;
            StartPoint.X = Left - StartPoint.X;
            StartPoint.Y = Top - StartPoint.Y;
            move = true;
        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            if (!move) return;
            Point p = Cursor.Position;
            Left = StartPoint.X + p.X;
            Top = StartPoint.Y + p.Y;
        }

        private void Form1_MouseUp(object sender, MouseEventArgs e)
        {
            move = false;
        }

        private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            savecfg();
            notifyIcon1.Visible = false;
            Environment.Exit(0);
        }

        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if (toolStripMenuItem1.Text == "展开")
            {
                //Height = 598;
                Height = 128;
                Width = 336;
                toolStripMenuItem1.Text = "收起";
            }
            else
            {
                int w = 0;
                foreach(Control c in panel1.Controls)
                {
                    w += (c.Visible ? 48 : 0);
                }
                Width = w;
                Height = 48;
                toolStripMenuItem1.Text = "展开";
            }
            
        }

        private void 置顶ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if(!TopMost)
            {
                置顶ToolStripMenuItem.Text = "☑置顶";
            }
            else
            {
                置顶ToolStripMenuItem.Text = "置顶";
            }
            TopMost = !TopMost;
        }

        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            Opacity = trackBar1.Value/100.0;
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            置顶ToolStripMenuItem_Click(null,null);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            
        }
    }
}
